!> \brief Contains the global variables and subroutines for reading data
!! from input files.
module input

   implicit none

   character(200) :: folderin = "./input_files/"   !< folder the for input files
   character(200) :: folderout = "./output_files/" !< folder the for output files
   character(200) :: logfile  !< name of the log file
   character(200) :: sname    !< simulations name
   character(200) :: ffit     !< name of executable for fitness calculation

   integer :: iarq = 10 !< number of the input file
   integer :: reload    !< upload backup data
   integer :: ind       !< number of the individual
   integer :: g         !< generation
   integer :: nu        !< number of unknowns
   integer :: np        !< population size
   integer :: ng        !< maximal number of generations
   integer :: nf        !< number of individuals for fitting RSM
   integer :: ext       !< use of Richardson extrapolation (0=no; 1=yes)
   integer :: kss       !< kind of search strategy
   integer :: kh        !< kind of hybridization (0=without; 1=RSM-min; 2=RSM-max)
   integer :: kp        !< kind of post processing (0=without; 1=SQP)
   integer :: kcm       !< kind of convergence measure (see the options in the subroutine get_convergence)
   integer :: ibest     !< index of the best individual in the population
   integer :: irsm = 0  !< index of the individual estimated by the RSM
   integer :: r(3)      !< indices of selected individuals

   integer :: clock
   integer :: seed(97)

   integer :: es        !< exit status (0=success; 1=failure)
   integer :: estatus   !< exit status (0=success; 1=failure)

   integer :: iproc     !< mpi: identification number of the process
   integer :: code      !< mpi: status code
   integer :: nproc     !< mpi: number of processes
   integer :: tag       !< mpi: message label
   integer :: comm      !< mpi: MPI communicator

   real(8) :: dif       !< differentiation constant
   real(8) :: crs       !< crossover constant
   real(8) :: xfit      !< fitness of the trial individual
   real(8) :: tcpu      !< total CPU time
   real(8) :: tcpu0     !< Accumulated CPU time
   real(8) :: tcpu1     !< starts CPU time
   real(8) :: tcpu2     !< finishes CPU time

   real(8) :: fitrsm    !< fitness of the individual xrsm obtained with the RSM
   real(8) :: cm        !< convergence measure
   real(8) :: detol     !< tolerance for the convergence measure in the DE algorithm

   real(8), dimension(:), allocatable :: x      !< trial individual
   real(8), dimension(:), allocatable :: xrsm   !< individual obtained with the RSM
   real(8), dimension(:), allocatable :: xmin   !< low boundary constraints
   real(8), dimension(:), allocatable :: xmax   !< high boundary constraints
   real(8), dimension(:), allocatable :: fit    !< fitness of the population
   real(8), dimension(:,:), allocatable :: pop  !< population

   character(10), dimension(:), allocatable :: xname !< names of the unknowns

contains

   !============================================================================

   !> \brief Gets the parameters from the input file
   subroutine get_parameters(   folderin, folderout, sname, iarq, reload, ffit, &
         tcpu0, ext, kss, kh, kp, kcm, nu, np, ng, dif, crs, detol, xmin, xmax, &
         xrsm, xname, x, fit, pop)
      implicit none
      character(200), intent(in) :: folderin    !< folder the for input files
      character(200), intent(inout) :: folderout!< folder the for output files
      character(200), intent(out) :: sname      !< simulations name
      character(200), intent(out) :: ffit       !< name of executable for fitness calculation
      integer, intent(inout) :: iarq   !< number of input file
      integer, intent(out) :: reload   !< upload backup data
      integer, intent(out) :: ext      !< Use of Richardson extrapolation (0=no; 1=yes)
      integer, intent(out) :: kss      !< kind of search strategy
      integer, intent(out) :: kh       !< kind of the hybridization (0=without; 1=RSM-min; 2=RSM-max)
      integer, intent(out) :: kp       !< kind of post processing (0=without; 1=SQP)
      integer, intent(out) :: kcm      !< kind of convergence measure (see the options in the subroutine get_convergence)
      integer, intent(out) :: nu       !< number of unknowns
      integer, intent(out) :: np       !< population size
      integer, intent(out) :: ng       !< maximal number of generations
      real(8), intent(out) :: tcpu0    !< accumulated CPU time
      real(8), intent(out) :: dif      !< differentiation constant
      real(8), intent(out) :: crs      !< crossover constant
      real(8), intent(out) :: detol    !< tolerance for the convergence measure in the DE algorithm
      real(8),       dimension(:),   allocatable, intent(out) :: x     !< trial individual
      real(8),       dimension(:),   allocatable, intent(out) :: xmin  !< low boundary constraints
      real(8),       dimension(:),   allocatable, intent(out) :: xmax  !< high boundary constraints
      real(8),       dimension(:),   allocatable, intent(out) :: xrsm  !< high boundary constraints
      character(10), dimension(:),   allocatable, intent(out) :: xname !< names of the unknowns
      real(8),       dimension(:),   allocatable, intent(out) :: fit   !< fitness of the population
      real(8),       dimension(:,:), allocatable, intent(out) :: pop   !< population

      character(200) :: arqin    !< input file name
      integer :: i

      open(10, file = trim(folderin) // "input_file.txt")
      read(10,*) arqin
      close(10)

      open(iarq, file = trim(folderin) // trim(adjustl(arqin)))

      read(iarq,*) sname
      read(iarq,*) reload

      folderout = trim(folderout) // trim(sname) // "/"

      tcpu0 = 0.d0

      read(iarq,*) ffit
      read(iarq,*) ext
      read(iarq,*) kss
      read(iarq,*) kh
      read(iarq,*) kp
      read(iarq,*) kcm
      read(iarq,*) nu
      read(iarq,*) np
      read(iarq,*) ng
      read(iarq,*) dif
      read(iarq,*) crs
      read(iarq,*) detol

      allocate(xmin(nu))
      allocate(xmax(nu))
      allocate(xrsm(nu))
      allocate(xname(nu))
      allocate(x(nu))
      allocate(fit(np))
      allocate(pop(np,nu))

      do i = 1, nu
         read(iarq,*) xname(i)
         read(iarq,*) xmin(i)
         read(iarq,*) xmax(i)
      end do

      close(10)

   end subroutine get_parameters

   !============================================================================

   ! \brief Loads the backup data
   subroutine load_backup(folderout, sname, nu, np, tcpu, g, fit, pop)
      implicit none
      character(200), intent(in) :: folderout   !< folder the for output files
      character(200), intent(in) :: sname       !< simulations name
      integer, intent(in)  :: nu           !< dimension of the problem
      integer, intent(in)  :: np           !< size of the population
      integer, intent(out) :: g            !< generation
      real(8), intent(out) :: tcpu         !< accumulated CPU time
      real(8), intent(out) :: fit(np)      !< fitness of the population
      real(8), intent(out) :: pop(np,nu)   !< population of chromosomes

      ! Inner variables

      integer :: ind ! Dummy index

      open(23, file = trim(folderout) // trim(sname) // "-backup.txt")

      read(23,*) tcpu ! " = tcpu:    Accumulated CPU time"

      read(23,*)    g ! " = g:       Last generation"

      read(23,*)

      do ind = 1, np

         read(23,*) fit(ind), pop(ind,:)

      end do

      read(23,*)

      close(23)

   end subroutine load_backup

end module input
